#include "PreforkServ.h"
#include <sys/wait.h>

static int nchildren;
static pid_t *pids;

int main(int argc, char** argv)
{
    int listenfd;
    socklen_t addrlen;

    if (argc == 1)
    {
        if ((listenfd = tcp_listen(NULL, NULL, &addrlen)) < 0)
        {
            err_quit("listenfd error\n");
        }
    }
    else if (argc == 4)
    {
        if ((listenfd = tcp_listen(argv[1], argv[2], &addrlen)) < 0)
        {
            err_quit("listenfd error\n");
        }
    }
    else
    {
        err_quit("usage : %s [host] [port] num of child", *argv);
    }

    nchildren = 10;
    pids = (pid_t*) malloc(nchildren*sizeof(pid_t));
    for (size_t i = 0; i < nchildren; i++)
    {
        pids[i] = child_make(i, listenfd, addrlen);
    }

    signal(SIGINT, sig_int);
    while (1)
    {
        pause();
    }
}


pid_t child_make(int i, int listenfd, int addrlen)
{
    pid_t pid;
    if ((pid = fork()) > 0)
    {
        //父进程，返回pid是子进程的id
        printf("pid :%x\n", pid);
        return pid;
    }
    child_main(i, listenfd, addrlen);
}

void child_main(int i, int listenfd, int addrlen)
{
    int connfd;
    socklen_t clilen;
    struct sockaddr* cliaddr;

    cliaddr = (struct sockaddr*) malloc(addrlen);
    printf("child %x starting\n", getpid());
    while (1)
    {
        clilen = addrlen;
        connfd = accept(listenfd, cliaddr, &clilen);
        if (connfd <= 0)
        {
            printf("connfd error\n");
            continue;
        }
        printf("current pid :%x\n", getpid());
        web_child(connfd);
        close(connfd);
    }
}


void sig_int(int signo)
{
    int i;
    for (size_t i = 0; i < nchildren; i++)
    {
        printf("kill the pid :%x\n", pids[i]);
        kill(pids[i], SIGTERM);
    }

    while (wait(NULL) > 0)
    {
    }

    if (errno != ECHILD)
    {
        err_sys("wait error");
    }
    
    pr_cpu_time();
    exit(0);
}


void web_child(int connfd)
{
    printf("str_echo :0x%x\n", connfd);
    size_t n;
    char buf[MAXLEN] = {0};

    while (1)
    {
        memset(buf, 0, sizeof(buf));
        n = read(connfd, buf, MAXLEN-1);
        if(n > 0)
        {
            write(connfd, buf, n);
            printf("server :%s\n", buf);
        }
        else if(n < 0 && errno == EINTR)
        {
            printf("continue to read\n");
            continue;
        }
        else
        {
            printf("unknown error, n :%ld\terrno :0x%x\n",n, errno);
            break;
        }
    }    
}